<?php
namespace Tlf\Scrawl\Ext\MdVerb;
class MainVerbs implements \Tlf\Scrawl\Extension {
/**
* a scrawl instance
*/
public \Tlf\Scrawl $scrawl;
/** array<string absolute_file_path, string relPath> array of files that didn't exist when see_file() was called */
protected array $see_file_failures = [];
public function __construct(\Tlf\Scrawl $scrawl){
$this->scrawl = $scrawl;
}
/**
* add callbacks to `$md_ext->handlers`
*/
public function setup_handlers(\Tlf\Scrawl\Ext\MdVerbs $md_ext){
$handlers = [
'import'=>'at_import',
'file' => 'at_file',
'template'=> 'at_template',
'link'=> 'at_link',
'easy_link'=> 'at_easy_link',
'hard_link'=> 'at_hard_link',
'see_file'=> 'at_see_file',
'see_files'=> 'at_see_files',
'see'=> 'at_see_file',
'system' => 'at_system',
];
foreach ($handlers as $verb=>$func_name){
$md_ext->handlers[$verb] = [$this, $func_name];
}
}
// public function okay(){}
/**
* Run a command on the computer's operating system.
*
* Supported options: `trim`, `trim_empty_lines`, `last_x_lines, int`
*
* @param $system_command string command to run on the system, like `git log`
* @param $options array of options.
*
* @return whatever is output by the system command
*/
public function at_system(string $system_command, ...$options){
//if (substr($system_command,0,3) == 'git'){
//echo "\n$system_command\n";
//exit;
//}
$this->scrawl->good("@system()", $system_command);
ob_start();
system("$system_command");
$output = ob_get_clean();
if (in_array('trim', $options)){
$output = trim($output);
}
if (in_array('trim_empty_lines', $options)){
$parts = explode("\n", $output);
while ($parts[0] == ''){
array_shift($parts);
}
while ($parts[count($parts)-1] == ''){
array_pop($parts);
}
$output = implode("\n", $parts);
}
if (in_array('last_x_lines', $options)){
$index = array_search('last_x_lines', $options);
$x = $options[$index+1];
$lines = explode("\n", $output);
$last_x_lines = array_slice($lines,-((int)$x));
$output = implode("\n", $last_x_lines);
}
return $output;
}
/**
* Load a template
* @usage @template(template_name, arg1, arg2)
*/
public function at_template(string $templateName, ...$templateArgs){
return $this->scrawl->get_template($templateName, $templateArgs);
}
/**
* Import something previously exported with `@export` or `@export_start/@export_end`
*
* @usage @import(Namespace.Key)
* @output whatever was exported by @export or @export_start/_end
*/
public function at_import(string $key){
$output = $this->scrawl->get('export',$key);
if ($output===null){
$this->scrawl->warn('@import', '@import('.$key.') failed');
$replacement = '# Import key "'.$key.'" not found.';
} else {
$replacement = $output;
}
return $replacement;
}
/**
* Copy a file's content into your markdown.
*
* @usage @file(rel/path/to/file.ext)
* @output the file's content, `trim`med.
*/
public function at_file(string $relFilePath){
$file = $this->scrawl->dir_root.'/'.$relFilePath;
if (!is_file($file)){
$this->scrawl->warn('@file', "@file($relFilePath) failed. File does not exist.");
return "'$file' is not a file.";
}
return trim(file_get_contents($file));
}
/**
* Outputs multiple markdown links separated by comma. Each argument is a `path;Name` combo, separated by a semicolon. The name is optional.
* Shorthand for multiple calls to `@see_file()`.
*
* @usage @see_files(/rel/path.md; Name, /rel/path2.md; Other, ...)
* @output `[Name](/rel/path.md), [Other](/rel/path2.md`)
*/
public function at_see_files(...$files){
$links = [];
foreach ($files as $arg){
$parts = explode(';', $arg);
$name = null;
if (isset($parts[1]))$name = trim($parts[1]);
$links[] = $this->at_see_file(trim($parts[0]), $name);
}
return implode(", ", $links);
}
/**
* Get a link to a file in your repo
*
* @usage @see_file(relative/file/path, OptionalLinkName)
* @output `[relative/file/path](urlPath)`
*/
public function at_see_file(string $relFilePath, ?string $link_name = null){
$path = $this->scrawl->dir_root.'/'.$relFilePath;
if (!is_file($path) && !is_dir($path)
&&filter_var($relFilePath, FILTER_VALIDATE_URL)===false
){
$this->see_file_failures[$path] = $relFilePath;
$this->scrawl->warn("@see_file","@see_file($relFilePath): File does not exist");
}
$urlPath = $relFilePath;
if ($urlPath[0]!='/')$urlPath = '/'.$urlPath;
$link_name = $link_name ?? $relFilePath;
$link = '['.$link_name.']('.$urlPath.')';
return $link;
}
/** just returns a regular markdown link. In future, may check validity of link or do some kind of logging
*
* @usage @hard_link(https://url.com, LinkName)
* @output [LinkName](https://url.com)
*/
public function at_hard_link(string $url, string $name=null){
if ($name==null) $name = $url;
return '['.$name.']('.$url.')';
}
/**
* Output links configured in your config json file.
* Config format is `{..., "links": { "link_name": "https://example.org"} }`
*
* @usage @link(phpunit)
* @output [LinkName](https://url.com)
*/
public function at_link(string $link_name, ?string $alternative_text = null){
$url = $this->scrawl->options['links'][$link_name] ?? null;
if ($url == null){
$this->scrawl->warn("Link not found", "Your config json does not include link \"$link_name\". Define like: `\"links\":{\"$link_name\": \"https://example.com\"}`");
return '(*error: link "'.$link_name.'" not found*)';
}
$header = "Link printed ($link_name)";
if ($alternative_text!=null)$link_name = $alternative_text;
$mdlink = '['.$link_name.']('.$url.')';
$this->scrawl->good($header, $mdlink);
return $mdlink;
}
/**
* Get a link to common services (twitter, gitlab, github, facebook)
*
* @usage @easy_link(twitter, TaelufDev)
* @output [TaelufDef](https://twitter.com/TaelufDev)
* @todo support a third param 'LinkName' so the target and link name need not be identical
*/
public function at_easy_link(string $service, string $target){
$sites = [
'twitter'=>'https://twitter.com/',
'gitlab'=>'https://gitlab.com/',
'github'=>'https://github.com/',
'facebook'=>'https://facebook.com/',
'tlf'=>'https://tluf.me/',
];
$host = $sites[strtolower($service)] ?? null;
if ($host==null){
$this->scrawl->warn('@easy_link', "@easy_link($service,$target): Service '$service' is not valid. Options are "
.implode(', ', array_keys($sites))
);
return "--service '$service' not found--";
}
$url = $host.$target;
$linkName = $target;
$mdLink = "[$linkName]($url)";
return $mdLink;
}
public function bootstrap(){}
public function ast_generated(string $className, array $ast){}
public function astlist_generated(array $asts){}
public function scan_filelist_loaded(array $code_files){}
public function scan_file_processed(string $path, string $relPath, string $file_content, array $file_exports){}
public function scan_filelist_processed(array $code_files, array $all_exports){}
public function doc_filelist_loaded(array $doc_files, \Tlf\Scrawl\Ext\MdVerbs $mdverb_ext){}
public function doc_file_loaded($path,$relPath,$file_content){}
public function doc_file_processed($path,$relPath,$file_content){}
public function doc_filelist_processed($doc_files){}
public function scrawl_finished(){
$actual_failures = [];
foreach ($this->see_file_failures as $abs_path => $rel_path){
if (is_file($abs_path) || is_dir($abs_path))continue;
$actual_failures[] = $rel_path;
}
if (count($actual_failures)==0){
$this->scrawl->good("@see_file()", "All referenced files exist.");
} else {
$msg = '@see_file() failed for the following files: '.implode(", ", $actual_failures);
$this->scrawl->warn("@see_file",$msg);
}
}
}